package com.code.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * JSON操作工具类
 *
 * @author xiaoyaowang
 */
@Slf4j
@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class JsonUtil {

    /**
     * ObjectMapper对象
     */
    private static ObjectMapper mapper = new ObjectMapper();

    static {
        mapper.setSerializationInclusion(Include.NON_NULL);
        //设置输入时忽略JSON字符串中存在而Java对象实际没有的属性，如果客户端传过来的参数明明符合json格式，但是服务器会报不能json格式化的错误，详情请查看 https://blog.csdn.net/aiyaya_/article/details/79446187
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 对象转化为json
     *
     * @param o 对象
     * @return json对象
     */
    public static String object2Json(Object o) {
        if (null == o) {
            return null;
        }

        String s = null;

        try {
            s = mapper.writeValueAsString(o);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return s;
    }

    /**
     * 判断字符串是否可以转化为json对象
     *
     * @param content 字符串
     * @return 是否可以转化为json对象的判断结果
     */
    public static boolean isJsonObject(String content) {
        // 此处应该注意，不要使用StringUtils.isEmpty(),因为当content为"  "空格字符串时，JSONObject.parseObject可以解析成功，
        // 实际上，这是没有什么意义的。所以content应该是非空白字符串且不为空，判断是否是JSON数组也是相同的情况。
        if (StringUtils.isBlank(content)) {
            return false;
        }
        try {
            JSONObject jsonStr = JSONObject.parseObject(content);
            log.info("判断字符串是否可以转化为json对象时，获取的json对象：[{}]", jsonStr.toJSONString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 判断字符串是否可以转化为JSON数组
     *
     * @param content 字符串
     * @return 是否可以转化为JSON数组的判断结果
     */
    public static boolean isJsonArray(String content) {
        if (StringUtils.isBlank(content)) {
            return false;
        }
        try {
            JSONArray jsonStr = JSONArray.parseArray(content);
            log.info("判断字符串是否可以转化为JSON数组时，获取的json数组：[{}]", jsonStr.toJSONString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * list对象转化为json数组
     *
     * @param objects list对象
     * @param <T>     list对象所属的类型
     * @return json数组
     */
    public static <T> List<String> listObject2ListJson(List<T> objects) {
        if (null == objects) {
            return null;
        }

        List<String> lists = new ArrayList<>();
        for (T t : objects) {
            lists.add(JsonUtil.object2Json(t));
        }

        return lists;
    }

    /**
     * json转化为集合对象
     *
     * @param jsons json对象
     * @param c     类型
     * @param <T>   集合对象类型
     * @return json转化为集合对象
     */
    public static <T> List<T> listJson2ListObject(List<String> jsons, Class<T> c) {
        if (null == jsons) {
            return null;
        }

        List<T> ts = new ArrayList<>();
        for (String j : jsons) {
            ts.add(JsonUtil.json2Object(j, c));
        }

        return ts;
    }

    public static <T> T json2Object(String json, Class<T> c) {
        if (!org.springframework.util.StringUtils.hasLength(json)) {
            return null;
        }

        T t = null;
        try {
            t = mapper.readValue(json, c);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    @SuppressWarnings("unchecked")
    public static <T> T json2Object(String json, TypeReference<T> tr) {
        if (!org.springframework.util.StringUtils.hasLength(json)) {
            return null;
        }

        T t = null;
        try {
            t = mapper.readValue(json, tr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }
}
